package com.moli.lumpSugar.user.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;

import com.moli.lumpSugar.common.annotation.RedissonLock;
import com.moli.lumpSugar.common.domain.vo.request.CursorPageBaseReq;
import com.moli.lumpSugar.common.domain.vo.request.PageBaseReq;
import com.moli.lumpSugar.common.domain.vo.response.CursorPageBaseResp;
import com.moli.lumpSugar.common.domain.vo.response.PageBaseResp;
import com.moli.lumpSugar.common.exception.BusinessException;
import com.moli.lumpSugar.common.utils.AssertUtil;
import com.moli.lumpSugar.user.dao.UserApplyDao;
import com.moli.lumpSugar.user.dao.UserDao;
import com.moli.lumpSugar.user.dao.UserFriendDao;
import com.moli.lumpSugar.user.domain.entity.User;
import com.moli.lumpSugar.user.domain.entity.UserApply;
import com.moli.lumpSugar.user.domain.entity.UserFriend;
import com.moli.lumpSugar.user.domain.vo.req.friend.FriendApplyReq;
import com.moli.lumpSugar.user.domain.vo.req.friend.FriendApproveReq;
import com.moli.lumpSugar.user.domain.vo.req.friend.FriendCheckReq;
import com.moli.lumpSugar.user.domain.vo.resp.FriendApplyResp;
import com.moli.lumpSugar.user.domain.vo.resp.FriendCheckResp;
import com.moli.lumpSugar.user.domain.vo.resp.FriendResp;
import com.moli.lumpSugar.user.domain.vo.resp.FriendUnreadResp;
import com.moli.lumpSugar.user.event.UserApplyEvent;
import com.moli.lumpSugar.user.service.FriendService;
import com.moli.lumpSugar.user.service.adapter.FriendAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @program: LumpSugarChat
 * @description:
 * @author: zhangjt
 * @create: 2024-10-30 09:06
 **/
@Service
@Slf4j
public class FriendServiceImpl implements FriendService {
    @Autowired
    private UserFriendDao userFriendDao;
    @Autowired
    private UserApplyDao userApplyDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    @Override
    public CursorPageBaseResp<FriendResp> friendList(Long uid, CursorPageBaseReq request) {
        // 先根据游标查出此用户所有的好友列表
        CursorPageBaseResp<UserFriend> userFriendList = userFriendDao.friendList(uid,request);
        if (userFriendList.isEmpty()) {
            return CursorPageBaseResp.empty();
        }
        // 将查出来的好友列表获取到所有的好友uid
        List<Long> friendUids = userFriendList.getList()
                .stream().map(UserFriend::getFriendUid)
                .collect(Collectors.toList());
        List<User> userList = userDao.getFriendList(friendUids);
        List<UserFriend> list = userFriendList.getList();
        return CursorPageBaseResp.init(userFriendList, FriendAdapter.buildFriend(list, userList));
    }

    @Override
    public void apply(Long uid, FriendApplyReq request) {
        // 先判断是否有好友关系
        UserFriend userFriend = userFriendDao.checkFriendIsHave(uid, request.getTargetUid());
        AssertUtil.isEmpty(userFriend, "好友关系已存在");
        // 判断是否有好友申请记录，自己申请的
        UserApply userApproving = userApplyDao.getFriendApproving(uid, request.getTargetUid());
        if (ObjectUtil.isNotNull(userApproving)){
            log.info("已有好友申请记录,uid:{}, targetId:{}", uid, request.getTargetUid());
            throw new BusinessException("您已添加申请，请耐心等待通过吧~~");
        }
        // 判断是否有好友申请记录，好友申请自己的
        UserApply friendApproving = userApplyDao.getFriendApproving(request.getTargetUid(),uid);
        if (ObjectUtil.isNotNull(friendApproving)){
            // 如果存在好友申请自己的记录，则调用同意好友申请
        }
        // 没有申请记录，则添加好友申请记录
        UserApply userApply = FriendAdapter.buildFriendApply(uid, request);
        userApplyDao.save(userApply);
        // 推送申请记录事件
        applicationEventPublisher.publishEvent(new UserApplyEvent(this,userApply));
    }

    @Override
    public FriendCheckResp check(Long uid, FriendCheckReq request) {
        FriendCheckResp result = new FriendCheckResp();
        List list = new ArrayList<>();
        // 查询传入的好友的uid哪些是自己的好友
        List<UserFriend> userFriendList = userFriendDao.check(uid, request.getUidList());
        // 获取好友的uid Set集合
        Set<Long> collect = userFriendList.stream().map(UserFriend::getFriendUid).collect(Collectors.toSet());
        // 遍历传入的uid，判断是否是自己的好友
        request.getUidList().forEach(item -> {
            FriendCheckResp.FriendCheck friendCheck = new FriendCheckResp.FriendCheck();
            friendCheck.setUid(item);
            if (collect.contains(item)){
                friendCheck.setIsFriend(true);
            }else {
                friendCheck.setIsFriend(false);
            }
            list.add(friendCheck);
        });
        result.setCheckedList(list);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @RedissonLock(key = "#uid")
    public void applyApprove(Long uid, FriendApproveReq request) {
        // 先判断申请列表是否存在此条申请记录
        UserApply haveUserApply = userApplyDao.isHaveUserApply(uid, request.getApplyId());
        AssertUtil.isNotEmpty(haveUserApply,"申请记录不存在");
        AssertUtil.equal(uid,haveUserApply.getTargetId(),"申请记录不存在");
        // 同意好友申请
        userApplyDao.agree(request.getApplyId());
        // 创建好友关系
        createFriend(uid,haveUserApply.getUid());
        // 创建好友房间
//        RoomFriend roomFriend = roomService.createFriendRoom(Arrays.asList(uid, haveUserApply.getUid()));
        // todo 发送一条同意消息。。我们已经是好友了，开始聊天吧
    }

    @Override
    public FriendUnreadResp unread(Long uid) {
        Integer unReadCount = userApplyDao.getUnReadCount(uid);
        FriendUnreadResp friendUnreadResp = new FriendUnreadResp();
        friendUnreadResp.setUnReadCount(unReadCount);
        return friendUnreadResp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFriend(Long uid, Long targetUid) {
        // 先判断是否是好友关系
        List<UserFriend> userFriend = userFriendDao.getUserFriend(uid, targetUid);
        AssertUtil.isNotEmpty(userFriend, "还不是好友哦，无需删除~~");
        List<Long> collect = userFriend.stream().map(UserFriend::getId).collect(Collectors.toList());
        userFriendDao.removeByIds(collect);
        // 取消好友房间
//        roomService.disableFriendRoom(Arrays.asList(uid, targetUid));
    }

    @Override
    public PageBaseResp<FriendApplyResp> pageApplyFriend(Long uid, PageBaseReq request) {
        IPage<UserApply> userApplyIPage = userApplyDao.friendApplyPage(uid, request.plusPage());
        if (CollectionUtil.isEmpty(userApplyIPage.getRecords())) {
            return PageBaseResp.empty();
        }
        //将这些申请列表设为已读
        readApples(uid, userApplyIPage);
        //返回消息
        return PageBaseResp.init(userApplyIPage, FriendAdapter.buildFriendApplyList(userApplyIPage.getRecords()));
    }

    private void readApples(Long uid, IPage<UserApply> userApplyIPage) {
        List<Long> applyIds = userApplyIPage.getRecords()
                .stream().map(UserApply::getId)
                .collect(Collectors.toList());
        userApplyDao.readApples(uid, applyIds);
    }

    private void createFriend(Long uid, Long targetUid) {
        UserFriend userFriend1 = new UserFriend();
        userFriend1.setUid(uid);
        userFriend1.setFriendUid(targetUid);
        UserFriend userFriend2 = new UserFriend();
        userFriend2.setUid(targetUid);
        userFriend2.setFriendUid(uid);
        userFriendDao.saveBatch(Lists.newArrayList(userFriend1, userFriend2));
    }
}
